<template>
	<view>
		<view class="BuuetoothServiceList">
			<text>蓝牙设备列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
				<view>
					<text>id: {{ item.deviceId }}</text>
				</view>
				<view>
					<text>信号强度(RSSI):{{item.RSSI}}</text>
				</view>
				<view>
					<text>name: {{ item.name }}</text>
				</view>
			</view>
		</scroll-view>
		<button @click="initBluetooth()"
			style="width: 9rem;height: 3rem;background-color: rgb(138, 145, 159);">①蓝牙连接</button>
		<button style="width: 9rem;height: 3rem;background-color: rgb(138, 145, 159);"
			@click="getyipeiduideshebeiList">已配对的设备列表</button>
		<view class="BuuetoothServiceList">
			<text>蓝牙服务列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in sevicesList">
				<view>
					<text user-select="true">uuid: {{ item.uuid }}</text>
				</view>
			</view>
		</scroll-view>
		<view class="BuuetoothServiceList">
			<text>蓝牙特征值列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in eigenvalueList">
				<view>
					<text user-select="true">uuid: {{ item.uuid }}</text>
				</view>
			</view>
		</scroll-view>

		<!-- <uni-easyinput type="text" v-model="formData.name" placeholder="请输入姓名" /> -->
		<view class="btnBox"><input type="text"
				style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
				placeholder="请输入蓝牙服务表中的uuid" v-model="serviceUuid" />
			<view class="clearInput">
				<icon type="clear" @click="clearIptA()"></icon>
			</view>
		</view>

		<view class="btnBox">
			<button @click="discovery()"
				style="width: 12rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">②搜索附近蓝牙设备</button>
			<button @click="getServices()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">③获取蓝牙服务</button>

			<button @click="getCharacteristics()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">②获取特征值</button>
			<button @click="notify()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button>
		</view>
		<view class="btnBox">
			<input type="text"
				style="box-shadow:0 0 8rpx #000;width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;margin-top: 20rpx;"
				placeholder="开始监听之前,请输入需要监听的特征值" v-model="eigenvalue" />
			<view class="clearInput">
				<icon type="clear" @click="clearIptB()"></icon>
			</view>
		</view>

		<view class="btnBox">
			<button @click="notify()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button>
			<input type="text"
				style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
				placeholder="请填写需要发送的内容" v-model="sendMessage" />
			<!-- <uni-icons type="icon-youxi" size="30"></uni-icons> -->
			<view class="clearInput">
				<icon type="clear" @click="clearIptC()"></icon>
			</view>
			<!-- <text style="background-color: aqua;height: 3rem;line-height: 3rem;margin-left: 2.5%;"></text> -->
			<button @click="send()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">④发送数据</button>
			<button @click="read()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">⑤读取数据</button>
		</view>
		<view class="msg_x" style="background-color: rgb(246, 244, 241);">
			<view class="msg_txt">
				监听到的内容：{{ message }}
			</view>
			<view class="msg_hex">
				监听到的内容（十六进制）：{{ messageHex }}
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				blueDeviceList: [],
				deviceId: null,
				sevicesList: [],
				serviceUuid: null,
				eigenvalueList: [],
				eigenvalue: null,
				message: "",
				messageHex: "",
				sendMessage: ""
			}
		},
		methods: {
			/**
			 * 获取当前已连接的设备
			 */
			getyipeiduideshebeiList() {
				uni.openBluetoothAdapter({
					success(res) {
						this.sevicesList = [];
						uni.showLoading({
							title: '开始获取已配对的设备..'
						})
						const main = plus.android.runtimeMainActivity();
						const Context = plus.android.importClass("android.content.Context");
						const BManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
						plus.android.importClass(BManager); //引入相关的method函数  
						const BAdapter = BManager.getAdapter();
						plus.android.importClass(BAdapter); //引入相关的method函数，这样之后才会有isEna  
						const lists = BAdapter.getBondedDevices();
						plus.android.importClass(lists);
						const iterator = lists.iterator();
						plus.android.importClass(iterator);
						while (iterator.hasNext()) {
							const d = iterator.next();
							plus.android.importClass(d);
							console.log("名称：" + d.getName() + "，地址：" + d.getAddress());
							console.log("类型：" + d.getType() + "，UUIDs：" + d.getUuids());
						}
						uni.hideLoading();
					},
					fail(err) {
						console.log('初始化蓝牙失败')
						console.error(err)
						uni.showToast({
							icon: 'none',
							title: '请确保系统蓝牙是打开状态'
						})
					}
				})

			},
			initBluetooth() {
				let that = this
				uni.openBluetoothAdapter({
					success(res) {
						console.log('初始化蓝牙成功')
						console.log(res)
						//开始搜索蓝牙设备
						that.discovery()
						//获取蓝牙服务
						console.log('调用服务预备');
						that.getServices()
					},
					fail(err) {
						console.log('初始化蓝牙失败')
						console.error(err)
					}
				})
			},
			// 开始搜索蓝牙设备
			discovery() {
				let that = this
				uni.startBluetoothDevicesDiscovery({
					//services:['FFE0'],
					success(res) {
						console.log('开始搜索')
						// 开启监听回调
						//uni.onBluetoothDeviceFound(that.found(res))
						uni.onBluetoothDeviceFound(function(res) {
							console.log(res, '---')
							if (res.devices[0].deviceId == '2C:C2:53:1C:2D:A7') {
								console.log('-------------------------- 找到苹果---------------', res);
							}
							// if (res.devices[0].name == "iCore Server") {
							if (res.devices[0]) {
								// 假设that.blueDeviceList是已经存在的设备列表数组
								let newDevice = res.devices[0];
								// 检查是否已经存在相同名称的设备
								let existingDevice = that.blueDeviceList.find(device => device.deviceId ===
									newDevice.deviceId);
								if (!existingDevice) {
									that.blueDeviceList.push(newDevice);
								}
							}

						})
					},
					fail(err) {
						console.log('搜索失败')
						console.error(err)
					}
				})
			},
			//连接蓝牙设备
			connect(data) {
				console.log(data, '---+++___')
				uni.showToast({
					icon: 'none',
					title: '开始连接设备:' + data.name
				})
				this.deviceId = data.deviceId
				let that = this
				uni.createBLEConnection({
					deviceId: this.deviceId,
					success(res) {
						uni.showToast({
							icon: 'success',
							title: '蓝牙连接成功'
						})
						console.log('连接成功')
						console.log(res)
						that.stopDiscovery()
						//获取蓝牙服务
						that.getServices()
					},
					fail(err) {
						uni.showToast({
							icon: 'error',
							title: '蓝牙连接失败'
						})
						console.log('连接失败')
						console.log(err)
					}
				})
			},
			//停止搜索
			stopDiscovery() {
				uni.stopBluetoothDevicesDiscovery({
					success(res) {
						console.log('停止成功')
						console.log(res)
					},
					fail(err) {
						console.log('停止失败')
						console.error(err)
					}
				})
			},
			//获取蓝牙服务
			getServices() {
				console.log('开始获取蓝牙服务');
				let that = this;
				uni.getBLEDeviceServices({
					deviceId: that.deviceId, // 设备ID，在上一步【4】里获取
					success(res) {
						that.sevicesList = res.services
						console.log('获取蓝牙服务=================获取蓝牙服务', that.sevicesList)
					},
					fail(err) {
						console.error(err)
					}
				})
			},
			//获取特征值
			getCharacteristics() {
				console.log('----获取特征值----')
				if (this.serviceUuid == null) {
					uni.showToast({
						icon: 'error',
						title: '请在上面输入框中输入uuid'
					})
				}
				let that = this
				//console.log(this.serviceUuid, 'serviceUuid')
				uni.getBLEDeviceCharacteristics({
					deviceId: that.deviceId, // 设备ID，在【4】里获取到
					serviceId: that.serviceUuid, // 服务UUID，在【6】里能获取到
					success(res) {
						that.eigenvalueList = res.characteristics
						console.log(res)
					},
					fail(err) {
						console.error(err)
					}
				})
			},
			notify() {
				let that = this
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					deviceId: that.deviceId, // 设备ID，在【4】里获取到
					serviceId: that.serviceUuid, // 服务UUID，在【6】里能获取到
					characteristicId: that.eigenvalue, // 特征值，在【7】里能获取到
					success(res) {
						console.log(res)

						// 接受消息的方法
						that.listenValueChange()
					},
					fail(err) {
						console.log(err)
					}
				})
			},
			// ArrayBuffer转16进度字符串示例
			ab2hex(buffer) {
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('')
			},
			// 将16进制的内容转成我们看得懂的字符串内容
			hexCharCodeToStr(hexCharCodeStr) {
				var trimedStr = hexCharCodeStr.trim();
				var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
				var len = rawStr.length;
				if (len % 2 !== 0) {
					alert("存在非法字符!");
					return "";
				}
				var curCharCode;
				var resultStr = [];
				for (var i = 0; i < len; i = i + 2) {
					curCharCode = parseInt(rawStr.substr(i, 2), 16);
					resultStr.push(String.fromCharCode(curCharCode));
				}
				return resultStr.join("");
			},
			listenValueChange() {
				let that = this
				uni.onBLECharacteristicValueChange(res => {
					// 结果
					console.log(res, '这是监听成功的回调');
					// 结果里有个value值，该值为 ArrayBuffer 类型，所以在控制台无法用肉眼观察到，必须将该值转换为16进制
					let resHex = that.ab2hex(res.value)
					//console.log(resHex)​;
					that.messageHex = resHex
					// 最后将16进制转换为ascii码，就能看到对应的结果
					let result = that.hexCharCodeToStr(resHex);
					that.message = String(result)
					console.log(String(result), '000000')
				})
			},

			//发送数据
			send() {
				// 向蓝牙设备发送一个0x00的16进制数据
				let msg = this.sendMessage
				console.log(msg, '$$$$$$$$$$$$$$$$$$$$$$$$$$');
				if (this.sendMessage == "") {
					uni.showToast({
						icon: 'error',
						title: '需要发送的内容不能为空'
					})
					return
				}


				const buffer = new ArrayBuffer(msg.length)
				const dataView = new DataView(buffer)
				// dataView.setUint8(0, 0)

				for (var i = 0; i < msg.length; i++) {
					dataView.setUint8(i, msg.charAt(i).charCodeAt())
				}

				let that = this

				uni.writeBLECharacteristicValue({
					deviceId: that.deviceId,
					serviceId: that.serviceUuid,
					characteristicId: that.eigenvalue,
					value: buffer,
					success(res) {
						console.log('writeBLECharacteristicValue success', res.errMsg)
						uni.showToast({
							title: 'write指令发送成功'
						})
					},
					fail(err) {
						console.error(err, "写入指令发送失败")
						uni.showToast({
							title: 'write指令发送失败',
							icon: 'error'
						})
					}
				})
			},
			//读取数据
			read() {
				let that = this
				uni.readBLECharacteristicValue({
					deviceId: that.deviceId,
					serviceId: that.serviceUuid,
					characteristicId: that.eigenvalue,
					success(res) {
						console.log(res, "数据读取成功")
						uni.showToast({
							title: 'read指令发送成功'
						})
					},
					fail(err) {
						console.error(err)
						uni.showToast({
							title: 'read指令发送失败',
							icon: 'error'
						})
					}
				})
			},
			//清除输入框中数据
			//清除蓝牙表中的uuid
			clearIptA() {
				this.serviceUuid = ""
			},
			//清除监听特定值的
			clearIptB() {
				this.eigenvalue = ""
			},
			//发送内容的输入框
			clearIptC() {
				this.sendMessage = ""
			}
		},
		onLoad() {

		}
	}
</script>

<style>
	.box {
		width: 100%;
		height: 500rpx;
		box-sizing: border-box;
		margin-bottom: 8rpx;
		border: 1px solid rgb(138, 145, 159);
	}

	.item {
		box-sizing: border-box;
		padding: 10rpx;
		border-bottom: 1px solid gray;
	}

	/* button {
		margin-bottom: 20rpx;
	} */

	.btnBox {
		display: flex;
		display: flex;
		align-items: flex-end;
		flex-wrap: wrap;
	}

	.BuuetoothServiceList {
		width: 100%;
		height: 2rem;
		margin-bottom: 8rpx;
		line-height: 2rem;
		text-align: center;
		font-weight: 700;

	}

	.msg_x {
		border: 2px solid seagreen;
		width: 98%;
		margin: 10rpx auto;
		box-sizing: border-box;
		padding: 20rpx;
	}

	/*	​.msg_txt {
		margin-bottom: 20rpx;
	} */

	.clearInput {
		width: 5%;
		height: 3rem;
		line-height: 3rem;
		float: left;
		margin-left: 2%;
	}
</style>